//使用C++11实现一个线程池,参考《深入应用C++11》中chapter9 实现
#ifndef __DANIEL_THREADPOOL_H__
#define __DANIEL_THREADPOOL_H__

#include <thread>
#include <mutex>
#include <condition_variable>
#include <deque>
#include <list>
#include <memory>
#include <vector>
#include <deque>
#include <functional>
#include <atomic>

//管理线程：1.线程不够，创建线程；2.空闲线程多，销毁线程；3.
//工作线程：工作或者堵塞(使用条件变量)；堵塞需要从任务队列取任务，执行；
//任务队列：使用function <void(void)>,通过bind可以传入任意参数
namespace daniel
{
    //任务队列类，通过一个List实现
    //两个条件变量：任务队列为空；无法取出任务；任务队列满，无法添加任务；
    //需要设置最大容量，防止当个任务处理时间过长，导致放入任务过多
    template <typename T>
    class SyncQueue
    {
    public:
        SyncQueue(uint32_t maxTasksNum):m_maxTasksNum(maxTasksNum),m_needStop{false}
        {
        }
        ~SyncQueue()
        {
            
        }
        //提供一个队列停止功能  队列停止，不能向其中添加任务
        void stop()
        {
            m_needStop=true;
            m_condQueueEmpty.notify_all();
            m_condQueueEmpty.notify_all();
        }
        //添加任务
        void addTask(const T& task)
        {
            //加锁，
            std::unique_lock<std::mutex> lock(m_mutex);
            //谓词为false，堵塞线程，直到谓词成立，接受notify
            m_condQueueFull.wait(lock,[=](){
               return !isFull()||!m_needStop;
            });
            m_tasksQueue.push_back(task);
            lock.unlock();
            m_condQueueEmpty.notify_one();
        }
        //批量添加任务
        void addTask(const std::list<T>& tasks)
        {
            
        }
        //取出任务
        T getTask()
        {
            //用unique_lock主要因为需要解锁
            std::unique_lock<std::mutex> lock(m_mutex);
            //队列为空时，堵塞，等待，直到队列不为空，接受唤醒信号
            m_condQueueEmpty.wait(lock,[=](){return !m_tasksQueue.empty();});
            T retTask=m_tasksQueue.front();
            m_tasksQueue.pop_front();
            lock.unlock();
            m_condQueueFull.notify_one();
            return retTask;
        }
        bool isEmpty()
        {
            std::lock_guard<std::mutex> lock(m_mutex);
            return m_tasksQueue.empty();
        }
    private:
        //队列是否已满
        bool isFull()
        {

            return m_tasksQueue.size()==m_maxTasksNum;
        }
        SyncQueue(const SyncQueue&)=delete;
        SyncQueue operator= (const SyncQueue&)=delete;
    private:
        uint32_t m_maxTasksNum;
        std::atomic<bool> m_needStop;
        std::list<T> m_tasksQueue;
        std::mutex m_mutex;
        //任务队列为空，取任务的时候堵塞
        std::condition_variable m_condQueueEmpty;
        //任务队列已满，放入任务的时候堵塞
        std::condition_variable m_condQueueFull;
    };

    class ThreadPool
    {
    public:
        using ptr=std::shared_ptr<ThreadPool>;
        //构造函数,指定创建的线程数目
        ThreadPool(uint32_t threadNum,uint32_t maxTaskNum);
        //析构函数
        ~ThreadPool() {}
        //线程调度函数，供管理者线程调用
        void manageFunc();
        //工作线程调用函数
        void workFunc();
        //添加工作任务的接口
        void addTask(std::function<void()> Func);
        void stop();
    private:
        ThreadPool() = delete;
        ThreadPool(const ThreadPool &) = delete;
        ThreadPool operator=(const ThreadPool &) = delete;

    private:
        uint32_t m_threadNum;
        //管理者线程和工作线程
        // std::thread m_manageThread;
        std::vector<std::thread> m_threads;
        //任务队列
        SyncQueue<std::function<void()>> m_tasks;
        //互斥量和条件变量，用于实现生产-消费者模型
        std::mutex m_mutex;
        //标志是否需要线程销毁
        std::atomic_bool m_needStop={false};
    };
}

#endif